using System;
using System.Web;
using System.Data;
using System.Text.RegularExpressions;
using System.Web.UI.HtmlControls;
using BlogEngine.Core.Web.Controls;
using BlogEngine.Core;

[Extension("SEO Pack: Optimizes your BlogEngine blog for Search Engines (SEO)", "0.2", "<a href=\"http://oberdata.com.ar/blog/post/2008/06/15/SEO-Pack-for-BlogengineNET.aspx\">Fabian Figueredo</a>")]
public class seopack
{
    static protected ExtensionSettings _settings = null;

    public seopack()
    {

        // Registers event handlers for serving both posts and pages.
        Post.Serving += new EventHandler<ServingEventArgs>(PostServingHandler);
        //Page.Serving += new EventHandler<ServingEventArgs>(PageServingHandler);
        //Page.Serving not work fine

        // create settings object. You need to pass exactly your
        // extension class name (case sencitive)
        ExtensionSettings settings = new ExtensionSettings("seopack");

        settings.AddParameter("ParamName", "ParamName", 70, true);
        settings.AddParameter("Value", "Value", 150, true);
        settings.AddParameter("Desc", "Value", 200, true);

        settings.Help = "Optimizes your BlogEngine blog for Search Engines (SEO).";

        settings.AddValues(new string[] { "HomeTitle", "", "HomeTitle" });
        settings.AddValues(new string[] { "HomeDescription", "", "HomeDescription" });
        settings.AddValues(new string[] { "HomeKeywords", "", "HomeKeywords" });
        settings.AddValues(new string[] { "PostTitleFormat", "[BlogTitle] - [PostTitle]", "[BlogTitle] = Blog Title [PostTitle] = Post Title" });
        settings.AddValues(new string[] { "PageTitleFormat", "[BlogTitle] - [PageTitle]", "[PageTitle] = Blog Title [PostTitle] = Page Title" });
        settings.AddValues(new string[] { "GenerateTextForDescPost", "YES", "Yes/No" });
        settings.AddValues(new string[] { "CharsForDescPost", "200", "Integer" });
        settings.AddValues(new string[] { "UseCategoriesForMetaKeywords", "YES", "Values: Yes/No" });
        settings.AddValues(new string[] { "UseTagsForMetaKeywords", "NO", "Values: Yes/No" });
        //------------------------------------------------------
        ExtensionManager.ImportSettings(settings);
        _settings = ExtensionManager.GetSettings("seopack");

        ExtensionManager.SetAdminPage("seopack", "~/seo/Admin.aspx");

    }

    private void PostServingHandler(object sender, ServingEventArgs e)
    {
        HttpContext context = HttpContext.Current;
        if (context != null)
        {
            System.Web.UI.Page page = context.CurrentHandler as System.Web.UI.Page;
            if (page != null)
            {
                SetTitle(sender, page);                
                AddMetaTagDesc(sender, page);
                AddMetaTagKeywords(sender, page);
            }
        }
    }

    private void PageServingHandler(object sender, ServingEventArgs e)
    {
        HttpContext context = HttpContext.Current;
        if (context != null)
        {
            System.Web.UI.Page page = context.CurrentHandler as System.Web.UI.Page;
            if (page != null)
            {
                SetTitle(sender, page);
                AddMetaTagDesc(sender, page);
                AddMetaTagKeywords(sender, page);
            }
        }
    }

    private void SetTitle<T>(T obj, System.Web.UI.Page page)
    {
        string strTitle = "";
        string param = "";
        if (!page.Request.RawUrl.ToUpper().Contains("DEFAULT.ASPX"))
        {
            string ti = "";
            if (obj is Post)
                ti = (obj as Post).Title;

            if (obj is Page)
                ti = (obj as Page).Title;

            param = GetValue("PostTitleFormat");
            if (!string.IsNullOrEmpty(param))
            {
                if (param.ToString() != "")
                {
                    strTitle = param.Replace("[BlogTitle]", BlogSettings.Instance.Name);
                    strTitle = strTitle.Replace("[PostTitle]", ti);
                }
            }
            page.Title = strTitle;

        }
        else {
            if (!page.Items.Contains("SeoPack-Title"))
            {
                param = GetValue("HomeTitle");
                if (!string.IsNullOrEmpty(param))
                {
                    if (param.ToString() != "")
                        page.Title = param;                    
                }
                // Sets a flag so only one title is added
                page.Items.Add("SeoPack-Title", 1);
            }
        }
    }

    private void AddMetaTagDesc<T>(T obj, System.Web.UI.Page page)
    {
        if (!page.Request.RawUrl.ToUpper().Contains("DEFAULT.ASPX"))
        {
            if (obj is Post)
            {
                int iCharCount;
                string strDesc = GetValue("GenerateTextForDescPost");
                try { iCharCount = int.Parse(GetValue("CharsForDescPost")); }
                catch { iCharCount = 50; }

                if (!string.IsNullOrEmpty(strDesc))
                {
                    if (strDesc.ToUpper() == "YES")
                    {
                        foreach (System.Web.UI.Control cr in page.Header.Controls)
                        {
                            try
                            {
                                if (((HtmlMeta)cr).Name.ToLower() == "description")
                                {
                                    page.Header.Controls.Remove(cr);
                                    break;
                                }
                            }
                            catch { }
                        }
                        strDesc = (obj as Post).Content;
                        strDesc = strDesc.Substring(0, iCharCount);
                        HtmlMeta MetaTag = new HtmlMeta();
                        MetaTag.Name = "Description";
                        MetaTag.Content = StripHtml(strDesc.Trim());
                        page.Header.Controls.Add(MetaTag);
                    }
                }
            }
        }
        else {
            if (!page.Items.Contains("SeoPack-Desc"))
            {                
                string param = GetValue("HomeDescription");
                if (!string.IsNullOrEmpty(param))
                {
                    foreach (System.Web.UI.Control cr in page.Header.Controls)
                    {
                        try
                        {
                            if (((HtmlMeta)cr).Name.ToLower() == "description")
                            {
                                page.Header.Controls.Remove(cr);
                                break;
                            }
                        }
                        catch { }
                    }
                    HtmlMeta MetaTag = new HtmlMeta();
                    MetaTag.Name = "Description";
                    MetaTag.Content = param;
                    page.Header.Controls.Add(MetaTag);                  
                }
                // Sets a flag so only one tag-desc is added
                page.Items.Add("SeoPack-Desc", 1);
            }        
        }
    }


    private void AddMetaTagKeywords<T>(T obj, System.Web.UI.Page page)
    {
        string param = "";
        if (!page.Request.RawUrl.ToUpper().Contains("DEFAULT.ASPX"))
        {
            if (obj is Post)
            {
                
                string strTags = "";
                param = GetValue("UseCategoriesForMetaKeywords");
                if (!string.IsNullOrEmpty(param))
                {
                    /// Tags --> Categories?
                    if (param.ToUpper() == "YES")
                    {
                        bool first = true;
                        foreach (Category c in (obj as Post).Categories)
                        {
                            if (first) strTags = c.Title;
                            else strTags = strTags + ", " + c.Title;
                            first = false;
                        }
                    }
                    else
                    {
                        /// Tags --> post.tags
                        param = GetValue("UseTagsForMetaKeywords");
                        if (!string.IsNullOrEmpty(param))
                        {
                            if (param.ToUpper() == "YES")
                            {
                                bool first = true;
                                foreach (string tag in (obj as Post).Tags)
                                {
                                    if (first) strTags = tag;
                                    else strTags = strTags + ", " + tag;
                                    first = false;
                                }
                            }
                        }
                    }
                }

                if (!string.IsNullOrEmpty(strTags))
                {
                    foreach (System.Web.UI.Control cr in page.Header.Controls)
                    {
                        try
                        {
                            if (((HtmlMeta)cr).Name.ToLower() == "keywords")
                            {
                                page.Header.Controls.Remove(cr);
                                break;
                            }
                        }
                        catch { }
                    }
                    HtmlMeta MetaTag = new HtmlMeta();
                    MetaTag.Name = "Keywords";
                    MetaTag.Content = page.Server.HtmlDecode(strTags.Trim());
                    page.Header.Controls.Add(MetaTag);
                }
            }
        }
        else
        {
            if (!page.Items.Contains("SeoPack-Key"))
            {
                param = GetValue("HomeKeywords");
                if (!string.IsNullOrEmpty(param))
                {
                    foreach (System.Web.UI.Control cr in page.Header.Controls)
                    {
                        try
                        {
                            if (((HtmlMeta)cr).Name.ToLower() == "keywords")
                            {
                                page.Header.Controls.Remove(cr);
                                break;
                            }
                        }
                        catch { }
                    }
                    HtmlMeta MetaTag = new HtmlMeta();
                    MetaTag.Name = "Keywords";
                    MetaTag.Content = param;
                    page.Header.Controls.Add(MetaTag);
                }
                // Sets a flag so only one tag-desc is added
                page.Items.Add("SeoPack-Key", 1);
            }
        }
    }

    private string GetValue(string param_name)
    {
        DataTable table = _settings.GetDataTable();
        foreach (DataRow row in table.Rows)
        {
            if (!string.IsNullOrEmpty((string)row["ParamName"]))
            {
                string strParam = (string)row["ParamName"];
                if (strParam == param_name)
                {
                    return (string)row["Value"];
                }
            }
        }
        return null;
    }

    private static Regex _Regex = new Regex("<[^>]*>", RegexOptions.Compiled);

    private static string StripHtml(string html)
    {
        if (string.IsNullOrEmpty(html))
            return string.Empty;


        html = _Regex.Replace(html, string.Empty);
        html = html.Replace("\r", "");
        html = html.Replace("\n", "");

        return html;
    }

}
